home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 076-100 / 092 / shar / sh.c < prev    next >
C/C++ Source or Header  |  1995-03-13  |  5KB  |  165 lines

  1. /* Sh.c
  2.  
  3.    Copyright (c) 1987 by F. G. Dufoe, III
  4.    All rights reserved.
  5.  
  6.    Permission is granted to redistribute this program provided the source
  7.    code is included in the distribution and this copyright notice is
  8.    unchanged.
  9.  
  10. */
  11.  
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include "Token.h"
  16.  
  17.  
  18. main(argc, argv)
  19.    /* This program unpacks a shell archive created by Shar.  If the user
  20.       typed more than one file name or typed a question mark on the command
  21.       line the program prints an error message and terminates.  Otherwise it
  22.       tries to open the specified file for input.  If it cannot open the
  23.       file it prints an error message and terminates. */
  24. int argc;
  25.    /* This is the number of arguments on the command line. */
  26. char **argv;
  27.    /* This points to a character array containing the argument values. */
  28. {
  29.    char ehd[512];
  30.       /* When we find a token which identifies the end of the "here
  31.          document" we'll store it here. */
  32.    int ehdl;
  33.       /* This is the length of the "end here document" string. */
  34.    char errmsg[256];
  35.       /* We'll use this character array to put together error messages which
  36.          contain variables. */
  37.    char *fgetline(FILE *);
  38.       /* This function gets the next line of text from a file. */
  39.    FILE *ifile;
  40.       /* This FILE pointer identifies the input file we want to read with
  41.          fgetline(). */
  42.    char *line;
  43.       /* This is the pointer to the line of text returned by fgetline(). */
  44.    int linelen;
  45.       /* This is the length of the line returned by fgetline(). */
  46.    enum
  47.    {
  48.       NEUTRAL,
  49.       COPY
  50.    } mode = NEUTRAL;
  51.       /* In NEUTRAL mode the program reads through the file looking for
  52.          "echo" and "cat" commands and their arguments.  In COPY mode it
  53.          writes each line to an output file until it encounters the text
  54.          string marking the end of the "here document". */
  55.    FILE *ofile;
  56.       /* This file pointer identifies the current output file. */
  57.    struct Token *parse(char *, char *);
  58.       /* This function parses a line of text. */
  59.    TOKEN state;
  60.       /* State is the token type of the previous token. */
  61.    char *text = NULL;
  62.       /* This points to the text buffer where the token text will be
  63.          stored. */
  64.    int textlen = 0;
  65.       /* This is the length of the buffer allocated for token text. */
  66.    struct Token *token;
  67.       /* This points to the list of Token structures returned by parse(). */
  68.  
  69.    if ((argc != 2) || (argv[1][0] == '?'))
  70.       fatal("Usage: Sh file.");
  71.       /* If the user requested one or provided the wrong number of arguments
  72.          print a usage message and terminate. */
  73.  
  74.    if ((ifile = fopen(*(argv + 1), "r")) == NULL)
  75.    {
  76.       sprintf(errmsg, "Sh: Can't open %s for input.", *(argv + 1));
  77.       fatal(errmsg);
  78.    }
  79.       /* If we can't open the input file print an error message and
  80.          terminate. */
  81.  
  82.    while ((line = fgetline(ifile)) != NULL)
  83.       /* Read the file, line by line, until we get to the end. */
  84.    {
  85.       switch (mode)
  86.       {
  87.       case NEUTRAL:
  88.          if (textlen < (linelen = strlen(line)))
  89.             /* If the line is longer than the text buffer we already have
  90.                let's get a new one. */
  91.          {
  92.             if (text != NULL)
  93.                free(text);
  94.                   /* If we had a text buffer allocated we must free it
  95.                      before we allocate another one. */
  96.             if ((text = malloc(linelen)) == NULL)
  97.                /* If we couldn't allocate memory for the token text print an
  98.                   error message and terminate. */
  99.                fatal("Sh: Couldn't allocate buffer for token text.");
  100.             textlen = linelen;
  101.                /* Remember the new text buffer length. */
  102.          }
  103.          token = parse(line, text);
  104.             /* Break the line down into tokens. */
  105.          switch (token->type)
  106.          {
  107.          case T_CAT:
  108.             while (token->next != NULL)
  109.             {
  110.                token = token->next;
  111.                switch (token->type)
  112.                {
  113.                case T_GT:
  114.                   state = T_GT;
  115.                   continue;
  116.                case T_LTLT:
  117.                   state = T_LTLT;
  118.                   continue;
  119.                case T_WORD:
  120.                   switch (state)
  121.                   {
  122.                   case T_GT:
  123.                      if ((ofile = fopen(token->text, "w")) == NULL)
  124.                      {
  125.                         sprintf(errmsg, "Sh: Can't open %s.", token->text);
  126.                         fatal(errmsg);
  127.                      }
  128.                      state = T_WORD;
  129.                      continue;
  130.                   case T_LTLT:
  131.                      strcpy(ehd, token->text);
  132.                      ehdl = strlen(ehd);
  133.                      mode = COPY;
  134.                      state = T_WORD;
  135.                      continue;
  136.                   }
  137.                }
  138.             }
  139.             continue;
  140.          case T_ECHO:
  141.             while (token->next != NULL)
  142.             {
  143.                token = token->next;
  144.                printf("%s ", token->text);
  145.             }
  146.             printf("\n");
  147.             continue;
  148.          }
  149.          continue;
  150.       case COPY:
  151.          if (strncmp(line, ehd, ehdl) == 0)
  152.             /* This line marks the "here document" end. */
  153.          {
  154.             mode = NEUTRAL;
  155.             fclose(ofile);
  156.             continue;
  157.          }
  158.          fprintf(ofile, "%s", line);
  159.          continue;
  160.       }
  161.    }
  162.    parse(NULL, NULL);
  163.    return(0);
  164. }
  165.